package net.awpspace.mobile.global;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;

import javax.microedition.io.Connector;
import javax.microedition.io.SocketConnection;

import net.awpspace.mobile.management.book.BookModel;

/**
 * Connection to server
 * 
 * @author Diep
 * 
 */
public class Client {

	public static String hostName;

	/**
	 * Singleton
	 */
	private static Client instance;

	private SocketConnection connection;
	private InputStream input;
	private OutputStream output;
	private byte[] buffer;

	private Client() {
		buffer = new byte[Global.BUFFER_SIZE];
	}

	public static Client getInstance() {
		if (instance == null) {
			instance = new Client();
			instance.init();
		}
		return instance;
	}

	/**
	 * Send username and password to server and wait for response
	 * 
	 * @param username
	 * @param password
	 * @return
	 */
	public boolean register(String username, String password) {
		try {
			output.write(Encode.build(Encode.REGISTER, new String[] {
					"username", "password" },
					new String[] { username, password }));
			input.read(buffer);
			String msg = new String(buffer, "UTF-8");
			resetBuffer();
			if (Encode.getType(msg) == Encode.RESULT) {
				return Encode.getResult(msg);
			}
		} catch (IOException e) {
			System.err.println("[Client.register():");
			e.printStackTrace();
			Utils.getInstance().alert(e.getMessage());
		}
		return false;
	}

	/**
	 * Send username and password to server and wait for response
	 * 
	 * @param username
	 * @param password
	 * @return
	 */
	public boolean login(String username, String password) {
		try {
			output.write(Encode.build(Encode.LOGIN, new String[] { "username",
					"password" }, new String[] { username, password }));
			input.read(buffer);
			String msg = new String(buffer, "UTF-8");
			resetBuffer();
			if (Encode.getType(msg) == Encode.RESULT) {
				return Encode.getResult(msg);
			}
		} catch (IOException e) {
			System.err.println("[Client.login():");
			e.printStackTrace();
			Utils.getInstance().alert(e.getMessage());
		}
		return false;
	}

	/**
	 * Request books from server
	 * 
	 * @return
	 */
	public Vector loadBooks() {
		try {
			output.write(Encode.build(Encode.LOAD, new String[] {},
					new String[] {}));
			StringBuffer msg = new StringBuffer();
			int eof = 0;
			String tmp;
			do {
				eof = input.read(buffer);
				tmp = new String(buffer, "UTF-8");
				msg.append(tmp);
				resetBuffer();
			} while (eof == Global.BUFFER_SIZE);
			String x = msg.toString();
			if (Encode.getType(x) == Encode.LOAD) {
				return Encode.getBooks(x);
			}
		} catch (IOException e) {
			System.err.println("[Client.load():");
			e.printStackTrace();
			Utils.getInstance().alert(e.getMessage());
		}
		return null;
	}

	/**
	 * Add a new book or update an existing book
	 * 
	 * @param id
	 */
	public void update(BookModel book) {
		try {
			output.write(Encode.build(
					Encode.UPDATE,
					new String[] { "id", "name", "author", "image",
							"description" },
					new String[] { book.getId() + "", book.getName(),
							book.getAuthor(), book.getImage(),
							book.getDescription() }));
		} catch (IOException e) {
			System.err.println("[Client.update():");
			e.printStackTrace();
			Utils.getInstance().alert(e.getMessage());
		}
	}

	/**
	 * Delete a book
	 * 
	 * @param id
	 */
	public void delete(int id) {
		try {
			output.write(Encode.build(Encode.DELETE, new String[] { "id" },
					new String[] { id + "" }));
		} catch (IOException e) {
			System.err.println("[Client.delete():");
			e.printStackTrace();
			Utils.getInstance().alert(e.getMessage());
		}
	}

	private void init() {
		StringBuffer host = new StringBuffer();
		host.append("socket://");
		host.append(hostName == null ? Global.HOST_NAME : hostName);
		host.append(':');
		host.append(Global.SERVER_PORT);
		try {
			connection = (SocketConnection) Connector.open(host.toString());
			input = connection.openInputStream();
			output = connection.openOutputStream();
		} catch (IOException e) {
			System.err.println("[Client.init():");
			e.printStackTrace();
			Utils.getInstance().alert(e.getMessage());
		}
	}

	private void resetBuffer() {
		for (int i = 0; i < Global.BUFFER_SIZE; ++i) {
			buffer[i] = 0;
		}
	}
}
